package com.example.front.arrange;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Task
 *
 * @author haojianfen
 */
@Slf4j
public abstract class AbstractTask<R> {

    private R result;

    private Future<R> future;

    private AbstractRootTask<?> rootTask;

    final R doHandle() throws Exception {
        if (result == null) {
            this.result = this.handle();
        }
        return result;
    }

    protected abstract R handle() throws Exception;

    final protected R getResult() {
        try {
            while (this.state.get() == INIT || future == null) {}
            return future.get();
        } catch (Exception e) {
            log.error("getResult error", e);
            throw new RuntimeException(e);
        }
    }

    final public void setResult(R result) {
        this.result = result;
    }

    public void setFuture(Future<R> future) {
        this.future = future;
    }

    public String getName() {
        return this.getClass().getName();
    }

    /**
     * 获取注解上声明的Task的返回结果
     * @param taskClass
     * @return
     * @param <T>
     */
    protected <T> T getDependResult(Class<? extends AbstractTask<T>> taskClass) {
        Assert.notNull(taskClass, "依赖的任务类型不能为空");
        if (taskClass == this.rootTask.getClass()) {
            return (T) this.rootTask.getResult();
        }
        for (AbstractTask<?> task : this.rootTask.getSubTaskList()) {
            if (task.getClass() == taskClass || task.getClass().getSuperclass() == taskClass) {
                return (T) task.getResult();
            }
        }
        throw new IllegalArgumentException("没有声明的依赖类型:" + taskClass.getName());
    }

    /**
     * 1-finish, 2-error, 3-working
     */
    private AtomicInteger state = new AtomicInteger(0);

    private static final int FINISH = 1;
    private static final int ERROR = 2;
    private static final int WORKING = 3;
    private static final int INIT = 0;


    private volatile int status;

    private List<AbstractTask<?>> parents = new ArrayList<>();

    private List<AbstractTask<?>> children = new ArrayList<>();

    /**
     * 判断所有任务执行完毕
     *
     * @param abstractSubTask
     * @return
     */
    public boolean isAllTaskDone() {
        return checkTaskDone(this.rootTask);
    }

//    public static Boolean checkTaskDone(AbstractTask<?> abstractTask) {
//        if (TaskStatusEnum.UN_FINISH.getStatus() == abstractTask.getStatus()) {
//            return false;
//        }
//        if (CollectionUtils.isNotEmpty(abstractTask.getChildren())) {
//            for (AbstractTask<?> child : abstractTask.getChildren()) {
//                if (!checkTaskDone(child)) {
//                    return false;
//                }
//            }
//        }
//        return true;
//    }

    private static Boolean checkTaskDone(AbstractRootTask<?> abstractRootTask) {
        for (AbstractTask<?> subTask : abstractRootTask.getSubTaskList()) {
            if (TaskStatusEnum.UN_FINISH.getStatus() == subTask.getStatus()) {
                return false;
            }
        }
        return true;
    }


    public static boolean isAllTaskSuccess(AbstractRootTask<?> abstractRootTask) {
        if (!checkTaskDone(abstractRootTask)) {
            return false;
        }
        for (AbstractTask<?> subTask : abstractRootTask.getSubTaskList()) {
            if (TaskStatusEnum.SUCCESS.getStatus() != subTask.getStatus()) {
                return false;
            }
        }
        return true;
    }
    /**
     * 判断所有任务是否执行成功
     *
     * @param abstractTask
     * @return
     */
    public static boolean isAllTaskSuccess(AbstractTask<?> abstractTask) {
        //拿到ROOT节点
        //while (null != abstractSubTask) {
        while (!abstractTask.getParents().isEmpty()) {
            abstractTask = abstractTask.getParents().get(0);
        }
        return checkTaskSuccess(abstractTask);
    }

    private static boolean checkTaskSuccess(AbstractTask<?> abstractTask) {
        if (TaskStatusEnum.FAIL.getStatus() == abstractTask.getStatus()) {
            return false;
        }
        if (CollectionUtils.isNotEmpty(abstractTask.getChildren())) {
            for (AbstractTask<?> child : abstractTask.getChildren()) {
                if (!checkTaskSuccess(child)) {
                    return false;
                }
            }
        }
        return true;
    }


    /**
     * 判断依赖任务是否执行完毕
     *
     * @return
     */
    public boolean isReady() {
        //log.info("task:{},isReady:{}", this.value == null ? "root" : this.value.getName(), Thread.currentThread().getName());
        boolean ready = true;
        //ROOT节点
//        if (null == this.getValue()) {
//            return true;
//        }
        for (AbstractTask<?> item : this.getParents()) {
            if (item.getStatus() == TaskStatusEnum.UN_FINISH.getStatus()) {
                return false;
            }
        }
        return ready;
    }

    public boolean isRunning() {
        return state.get() == WORKING;
    }

    public boolean startRun() {
        return this.state.compareAndSet(INIT, WORKING);
        //return true;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public List<AbstractTask<?>> getParents() {
        return parents;
    }

    public void setParents(List<AbstractTask<?>> parents) {
        this.parents = parents;
    }

    public List<AbstractTask<?>> getChildren() {
        return children;
    }

    public void setChildren(List<AbstractTask<?>> children) {
        this.children = children;
    }

    public AbstractRootTask getRootTask() {
        return rootTask;
    }

    public void setRootTask(AbstractRootTask abstractRootTask) {
        this.rootTask = abstractRootTask;
    }
}
